#include <util/message.hpp>
#include "vset.hpp"

namespace {
  util::message_stream<char> vverr ("\nVV::VSET ERROR: ");
  util::message_stream<char> vvwarn("\nVV::VSET WARNING: ");
}

/** @brief Constructor
    @param start The iterator to the first position in the set
    @param end The iterator to the last poisition in the set
*/
vv::vset_iterator::vset_iterator(std::set<abstract_vertex*>::iterator start, std::set<abstract_vertex*>::iterator end) :
  start(start),
  end(end),
  current(start)
{
  if (start == end)
    vverr << "Attempt to iterate on an empty set." << std::endl;
}

/** @brief Return the first element of the set */
vv::vptr vv::vset_iterator::first() {
  return *start;
}

/** @brief Return the next element of the set */
vv::vptr vv::vset_iterator::advance() {
  ++current;
  if (current != end)
    return *current;
  else
    return 0;
}

/** @brief Check if there's more to vertices to iterate over */
bool vv::vset_iterator::not_finished() {
  return current != end;
}

/** @brief Add a vertex to the set
    @param v The vertex to add
*/
void vv::vset::add(vv::vptr v) {
  if (!v) {
    vvwarn << "add() -- The vertex was null.  The set was not modified." << std::endl;
    return;
  }
  if (vertices.insert(v.raw()).second)
    v->refp();
}

/** @brief Remove a vertex to the set
    @param v The vertex to remove
*/
void vv::vset::remove(vv::vptr v) {
  if (!v) {
    vvwarn << "remove() -- The vertex was null.  The set was not modified." << std::endl;
  }
  if (vertices.find(v.raw()) != vertices.end()) {
    v->refm();
    vertices.erase(v.raw());
  }
}

/** @brief Synchronise the vertices in the set */
void vv::vset::synchronise() {
  for (vsiter i = vertices.begin(); i != vertices.end(); ++i)
    (*i)->synchronise();
}

/* @brief Assignment
   @param s The set to assign from
*/
void vv::vset::operator=(const vv::vset& s) {
  vertices.clear();
  vertices = s.vertices; 
}

/* @brief Addition assignment
   @param s The set to add

   This function makes the set the union of itself and @a s.
*/
void vv::vset::operator+=(const vv::vset& s) {
  for (vsiter i = s.vertices.begin(); i != s.vertices.end(); ++i)
    vertices.insert(*i);
}

/* @brief Subtraction assignment
   @param s The set to remove

   This function makes the set the difference of itself and @a s.
*/
void vv::vset::operator-=(const vv::vset& s) {
  for (vsiter i = s.vertices.begin(); i != s.vertices.end(); ++i)
    vertices.erase(*i);
}

vv::vset_iterator* vv::vset::iter() {
  return new vset_iterator(vertices.begin(), vertices.end());
}
